package com.demon.net.converter

import com.demon.net.json.*
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.internal.bind.TypeAdapters
import com.google.gson.reflect.TypeToken
import okhttp3.RequestBody
import okhttp3.ResponseBody
import retrofit2.Converter
import retrofit2.Converter.Factory
import retrofit2.Retrofit
import java.lang.reflect.Type

open class CustomGsonConverterFactory private constructor(gson: Gson?) : Factory() {
    private val gson: Gson
    override fun responseBodyConverter(
            type: Type,
            annotations: Array<Annotation>,
            retrofit: Retrofit
    ): Converter<ResponseBody, *> {
        val adapter = gson.getAdapter(TypeToken.get(type))
        return CustomResponseConverter<Any>(gson, adapter, type)
    }

    override fun requestBodyConverter(
            type: Type,
            parameterAnnotations: Array<Annotation>,
            methodAnnotations: Array<Annotation>,
            retrofit: Retrofit
    ): Converter<*, RequestBody>? {
        return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit)
    }

    companion object {
        @JvmOverloads
        fun create(gson: Gson? = getGson()): CustomGsonConverterFactory {
            return CustomGsonConverterFactory(gson)
        }

        private fun getGson(): Gson {
            //Json 容错处理
            return GsonBuilder()
                    .registerTypeAdapterFactory(
                            TypeAdapters.newFactory(
                                    String::class.java,
                                    StringTypeAdapter()
                            )
                    )
                    .registerTypeAdapterFactory(
                            TypeAdapters.newFactory(
                                    Boolean::class.javaPrimitiveType,
                                    Boolean::class.java,
                                    BooleanTypeAdapter()
                            )
                    )
                    .registerTypeAdapterFactory(
                            TypeAdapters.newFactory(
                                    Int::class.javaPrimitiveType,
                                    Int::class.java,
                                    IntegerTypeAdapter()
                            )
                    )
                    .registerTypeAdapterFactory(
                            TypeAdapters.newFactory(
                                    Long::class.javaPrimitiveType,
                                    Long::class.java,
                                    LongTypeAdapter()
                            )
                    )
                    .registerTypeAdapterFactory(
                            TypeAdapters.newFactory(
                                    Float::class.javaPrimitiveType,
                                    Float::class.java,
                                    FloatTypeAdapter()
                            )
                    )
                    .registerTypeAdapterFactory(
                            TypeAdapters.newFactory(
                                    Double::class.javaPrimitiveType,
                                    Double::class.java,
                                    DoubleTypeAdapter()
                            )
                    )
                    .registerTypeHierarchyAdapter(MutableList::class.java, ListTypeAdapter())
                    .create()
        }
    }

    init {
        if (gson == null) throw NullPointerException("gson == null")
        this.gson = gson
    }
}